home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / Apple Game Sprockets / NetSprocket / NewNSpTest Sources / NetStuff.cp < prev    next >
Encoding:
Text File  |  1997-09-18  |  19.5 KB  |  908 lines  |  [TEXT/CWIE]

  1. //•    ------------------------------------------------------------------------------------------    •
  2. //•
  3. //•    Copyright © 1996, 1997 Apple Computer, Inc., All Rights Reserved
  4. //•
  5. //•
  6. //•        You may incorporate this sample code into your applications without
  7. //•        restriction, though the sample code has been provided "AS IS" and the
  8. //•        responsibility for its operation is 100% yours.  However, what you are
  9. //•        not permitted to do is to redistribute the source as "DSC Sample Code"
  10. //•        after having made changes. If you're going to re-distribute the source,
  11. //•        we require that you make it clear in the source that the code was
  12. //•        descended from Apple Sample Code, but that you've made changes.
  13. //•
  14. //•        Authors:
  15. //•            Jamie Osborne
  16. //•            Chris De Salvo
  17. //•
  18. //•    ------------------------------------------------------------------------------------------    •
  19.  
  20. //•    ------------------------------    Includes
  21.  
  22. #include "NetStuff.h"
  23.  
  24. #include <PLStringFuncs.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27.  
  28. //•    ------------------------------    Private Definitions
  29.  
  30. //•    If this is set to 1 then the player enumeration menu item iterates by calling NSpPlayer_GetInfo
  31. //•    rather than using the data in the PlayerEnumeration data structure.  This is merely for coverage
  32. //•    testing of the GetInfo call on the client side.
  33. #define USE_PLAYER_GET_INFO            0
  34.  
  35. //•    ------------------------------    Private Types
  36.  
  37. enum
  38. {
  39.     kStandardMessageSize    = 1500,
  40.     kBufferSize                = 0, 
  41.     kQElements                = 0,
  42.     kTimeout                = 5000,
  43.     kMaxPlayers                = 8
  44. };
  45.  
  46. //•    ------------------------------    Private Variables
  47.  
  48. static Str31                gameName;
  49. static Str31                password;
  50. static Str31                playerName;
  51. static Str31                kJoinDialogLabel = "\pChoose a Game:";
  52. static Boolean                gInCallback = false;
  53. static UInt32                gLastUpdate = 0;
  54. static UInt32                gUpdateFrequency = 2;
  55. static PlayerInputMessage    gPlayerMessage;
  56. static UInt32                gPlayerMessageSize = 400;
  57. static GameStateMessage        gGameStateMessage;
  58. static UInt32                gGameStateMessageSize = 1024;
  59. static UInt32                gSendOptions = kNSpSendFlag_Normal;
  60. static UInt32                gHostSendOptions = kNSpSendFlag_Registered | kNSpSendFlag_SelfSend;
  61. static MenuHandle            gHostMenuH;
  62. static UInt32                gHostUpdateFrequency = 2;
  63. static UInt32                gLastHostUpdate = 0;
  64. static WindowStuff            gWindowStuff[8];
  65. static NSpPlayerID            gMyPlayerID = 0;
  66.  
  67. //•    ------------------------------    Private Functions
  68.  
  69. static WindowStuff *GetFreeWindowStuff(void);
  70. static void ReleaseWindowStuff(WindowStuff *inStuff);
  71. static WindowStuff *GetPlayersWindowStuff(NSpPlayerID inPlayer);
  72. static WindowPtr FindPlayersWindow(NSpPlayerID inPlayer);
  73. static void InvalPlayerWindow(NSpPlayerID inPlayer);
  74. static pascal Boolean MessageHandler(NSpGameReference inGameRef, NSpMessageHeader *inMessage, void *inContext);
  75. static void InitNetMenu(MenuHandle menu);
  76. static void GetChooserName(Str255 name);
  77. static void CloseAllWindows(void);
  78. static void AddHostMenu(void);
  79. static void DoAdjustMenu(MenuRef m, UInt32 options, UInt32 updateFrequency, UInt32 messageSize);
  80. static void DoSendLeaveMessage(NSpPlayerID inID);
  81. static void DoHandleMessage(NSpMessageHeader *inMessage);
  82. static void GetMessages(void);
  83. static void UpdateNetWindows(void);
  84.  
  85. static void GetInfoEnumeratePlayers(void);
  86. static void EnumeratePlayers(void);
  87.  
  88. //•    ------------------------------    Public Variables
  89.  
  90. Boolean             gHost = false;
  91. NSpGameReference    gNetGame = nil;
  92.  
  93. //•    --------------------    GetFreeWindowStuff
  94.  
  95. // this is not reentrant
  96. static WindowStuff *
  97. GetFreeWindowStuff(void)
  98. {
  99.     for (int i = 0; i < 8; i++)
  100.     {
  101.         if (gWindowStuff[i].id == 0)
  102.             return &gWindowStuff[i];
  103.     }
  104.     
  105.     return nil;
  106. }
  107.  
  108. //•    --------------------    ReleaseWindowStuff
  109.  
  110. static void
  111. ReleaseWindowStuff(WindowStuff *inStuff)
  112. {
  113.     if (inStuff == nil)
  114.         printf("passed in nill stuff pointer!\n");
  115.     else
  116.         memset(inStuff, 0, sizeof(WindowStuff));
  117. }
  118.  
  119. //•    --------------------    GetPlayersWindowStuff
  120.  
  121. static WindowStuff *
  122. GetPlayersWindowStuff(NSpPlayerID inPlayer)
  123. {
  124.     for (int i = 0; i < 8; i++)
  125.     {
  126.         if (gWindowStuff[i].id == inPlayer)
  127.             return &gWindowStuff[i];
  128.     }
  129.     
  130.     return nil;
  131.  
  132. }
  133.  
  134. //•    --------------------    FindPlayersWindow
  135. //•
  136. //•        Finds the window associated with the given player
  137. static WindowPtr
  138. FindPlayersWindow(NSpPlayerID inPlayer)
  139. {
  140.     WindowPtr    w;
  141.     WindowStuff *stuff;
  142.     w = FrontWindow();
  143.  
  144.     while (w != nil)
  145.     {
  146.         stuff = (WindowStuff *) GetWRefCon(w);    
  147.         if (stuff->id == inPlayer)
  148.             break;
  149.         else
  150.             w = GetNextWindow(w);
  151.     }
  152.     
  153.     return w;
  154. }
  155.  
  156. //•    --------------------    InvalPlayerWindow
  157.  
  158. static void
  159. InvalPlayerWindow(NSpPlayerID inPlayer)
  160. {
  161. WindowPtr    w = FindPlayersWindow(inPlayer);
  162.  
  163.     if (w)
  164.     {
  165.     GrafPtr        oldPort;
  166.     
  167.         GetPort(&oldPort);
  168.         SetPort(w);
  169.         InvalRect(&w->portRect);
  170.         SetPort(oldPort);
  171.     }
  172. }
  173.  
  174.  
  175. //•    --------------------    MessageHandler
  176. //•
  177. //•    this function gets called every time NetSprocket receives a new message.
  178. //•    we use it to prevent our message q from getting too full if we don't idle enough
  179. //•    a good example is when the user has clicked in the menu bar and is reading menus
  180.  
  181. static pascal Boolean
  182. MessageHandler(NSpGameReference inGameRef, NSpMessageHeader *inMessage, void *inContext)
  183. {
  184.     gInCallback = true;
  185. //    if it's a system message, just leave it in the q, so that we can handle it later (when we're
  186. //    not at interrupt time)
  187.     if (inMessage->what & kNSpSystemMessagePrefix)
  188.         return true;    // tells NetSprocket to put the message in the message Q
  189.     else    // it's one of ours
  190.     {
  191.  
  192.         if (inMessage->what == kPlayerInputMessage && gHost)
  193.         {            
  194.             WindowStuff *stuff = GetPlayersWindowStuff(inMessage->from);
  195.             if (stuff)
  196.             {
  197.                 stuff->lastMessage = inMessage->id;
  198.                 stuff->changed = true;
  199.             }                
  200.             return false;
  201.         }
  202.         else if (inMessage->what == kGameStateMessage && !gHost)
  203.         {
  204.             WindowStuff *stuff = GetPlayersWindowStuff(gMyPlayerID);
  205.             if (stuff)
  206.             {
  207.                 stuff->lastMessage = inMessage->id;
  208.                 stuff->changed = true;
  209.             }                
  210.             return false;
  211.         }
  212.     }
  213.     gInCallback = false;
  214.  
  215.     //•    If it's some state we haven't considered then better leave it in the queue
  216.     return (true);
  217. }
  218.  
  219. //•    --------------------    GetChooserName
  220.  
  221. static void
  222. GetChooserName(Str255 name)
  223. {
  224. StringHandle    userName;
  225.     
  226.     userName = GetString(-16096);
  227.     if (userName == nil)
  228.     {
  229.         name[0] = 0;
  230.     }
  231.     else
  232.     {    
  233.         PLstrcpy(name, *userName);
  234.         ReleaseResource ((Handle) userName);
  235.     }
  236. }
  237.  
  238. //•    --------------------    RefreshWindow
  239.  
  240. void
  241. RefreshWindow(WindowPtr inWindow)
  242. {
  243.     WindowStuff *stuff = (WindowStuff *) GetWRefCon(inWindow);
  244.     
  245.     if (stuff->lastMessage != 0)
  246.         NumToString(stuff->lastMessage, stuff->text);
  247.  
  248.     EraseRect(&inWindow->portRect);
  249.     
  250.     MoveTo(20,20);
  251.     DrawString(stuff->text);    
  252. }
  253.  
  254.  
  255. //•    --------------------    InitNetMenu
  256.  
  257. static void
  258. InitNetMenu(MenuHandle menu)
  259. {
  260.     SetItemMark(menu, iJunk, noMark);
  261.     SetItemMark(menu, iNormal, noMark);
  262.     SetItemMark(menu, iRegistered, noMark);
  263.     SetItemMark(menu, iBlocking, noMark);
  264.     SetItemMark(menu, i1X, noMark);
  265.     SetItemMark(menu, i10X, noMark);
  266.     SetItemMark(menu, i30X, noMark);
  267.     SetItemMark(menu, iNoLimit, noMark);
  268.     SetItemMark(menu, iLess500, noMark);
  269.     SetItemMark(menu, i1K, noMark);
  270.     SetItemMark(menu, i10K, noMark);
  271.     SetItemMark(menu, i100K, noMark);
  272. }
  273.  
  274. //•    --------------------    InitNetworking
  275.  
  276. OSStatus
  277. InitNetworking(NSpGameID inGameID)
  278. {
  279.     OSStatus    status;
  280.     
  281.     printf("Initializing NetSprocket... ");
  282.     memset(gWindowStuff, 0, sizeof(WindowStuff) * 8);
  283.     status = NSpInitialize(kStandardMessageSize, kBufferSize, kQElements, inGameID, kTimeout);
  284.     if (status != noErr)
  285.         printf("NSpInitialize returned error %d\n", status);
  286.     else
  287.         printf("Done\n");
  288.         
  289. //    Install an async message handler.  We do this so that we won't get hosed if we
  290. //    don't call HandleNetworking often enough (such as a tight loop for mouse-down
  291.     status = NSpInstallAsyncMessageHandler(MessageHandler, nil);
  292.     if (status != noErr)
  293.         printf("NSpInstallAsyncMessageHandler returned error %d\n", status);
  294.     
  295.     MenuHandle h = GetMenuHandle(131);
  296.     if (h)
  297.         InitNetMenu(h);
  298.     
  299.     return status;
  300. }
  301.  
  302.  
  303. //•    --------------------    CloseAllWindows
  304.  
  305. static void
  306. CloseAllWindows(void)
  307. {
  308. WindowPtr    w, nextWind;
  309.  
  310.     w = FrontWindow();
  311.  
  312.     while (w != nil)
  313.     {
  314.         nextWind = GetNextWindow(w);
  315.         WindowStuff *stuff = (WindowStuff *) GetWRefCon(w);
  316.         if (stuff)
  317.         {
  318.             DisposePtr((Ptr) stuff);
  319.             DisposeWindow(w);
  320.         }        
  321.         w = nextWind;
  322.     }
  323. }
  324.  
  325.  
  326. //•    --------------------    ShutdownNetworking
  327.  
  328. void
  329. ShutdownNetworking(void)
  330. {
  331. OSStatus    status;
  332.     
  333.     if (gNetGame)
  334.     {
  335.         status = NSpGame_Dispose( gNetGame, 0 );
  336.         if (status != noErr)
  337.         {
  338.             printf("NSpGame_Dispose returned error %d\n", status);
  339. //            I REALLY want it to shutdown
  340.             status = NSpGame_Dispose( gNetGame, kNSpGameFlag_ForceTerminateGame );    
  341.             if (status != noErr)
  342.                 printf("NSpGame_Dispose (force) returned error %d\n", status);
  343.         }
  344.         
  345.         if (gHost)
  346.         {
  347.             DeleteMenu(132);
  348.             ReleaseResource((Handle) gHostMenuH);
  349.             DrawMenuBar();
  350.         }
  351.  
  352.         gNetGame = NULL;
  353.     }
  354.  
  355. //    if there are any windows left, kill them
  356.     CloseAllWindows();
  357. }
  358.  
  359.  
  360. //•    --------------------    AddHostMenu
  361.  
  362. static void
  363. AddHostMenu(void)
  364. {
  365.     gHostMenuH = GetMenu(132);
  366.     if (gHostMenuH == nil)
  367.         DebugStr("\pCouldn't find menu resource!");
  368.     else
  369.         InsertMenu(gHostMenuH, 0);
  370.         
  371.     InitNetMenu(gHostMenuH);
  372.     
  373.     DrawMenuBar();
  374. }
  375.  
  376. //•    --------------------    HandleNetMenuChoice
  377.  
  378. void
  379. HandleNetMenuChoice(short menu, short item)
  380. {
  381.     MenuHandle h = GetMenuHandle(menu);
  382.     UInt32 *options;
  383.     UInt32 *frequency;
  384.     UInt32 *size;
  385.  
  386.     if (menu == 132)    // host menu
  387.     {
  388.         options = &gHostSendOptions;
  389.         frequency = &gHostUpdateFrequency;
  390.         size = &gGameStateMessageSize;
  391.     }
  392.     else
  393.     {
  394.         options = &gSendOptions;
  395.         frequency = &gUpdateFrequency;
  396.         size = &gPlayerMessageSize;
  397.     }
  398.                 
  399.     switch(item)
  400.     {
  401.         case iJunk:
  402.             *options &= 0xFF0FFFFF;
  403.             *options |= kNSpSendFlag_Junk;
  404.         break;
  405.         case iNormal:
  406.             *options &= 0xFF0FFFFF;
  407.             *options |= kNSpSendFlag_Normal;
  408.         break;
  409.         case iRegistered:
  410.             *options &= 0xFF0FFFFF;
  411.             *options |= kNSpSendFlag_Registered;
  412.         break;
  413.         case iBlocking:
  414.             if (*options & kNSpSendFlag_Blocking)
  415.                 *options &= ~kNSpSendFlag_Blocking;
  416.             else
  417.                 *options |= kNSpSendFlag_Blocking;
  418.         break;
  419.         case i1X:
  420.             *frequency = 60;
  421.             break;
  422.             
  423.         case i10X:
  424.             *frequency = 6;
  425.             break;
  426.             
  427.         case i30X:
  428.             *frequency = 2;
  429.             break;
  430.             
  431.         case iNoLimit:
  432.             *frequency = 0;
  433.             break;
  434.             
  435.         case iLess500:
  436.             *size = 400;
  437.             break;
  438.             
  439.         case i1K:
  440.             *size = 1024;
  441.             break;
  442.             
  443.         case i10K:
  444.             *size = 10240;
  445.             break;
  446.             
  447.         case i100K:
  448.             *size = 102400;
  449.             break;
  450.             
  451.         case iEnumerate:
  452. #if USE_PLAYER_GET_INFO
  453.             if (131 == menu)
  454.                 GetInfoEnumeratePlayers();
  455.             else
  456. #endif
  457.                 EnumeratePlayers();
  458.             break;
  459.             
  460.         default:
  461.         break;
  462.     }
  463.     
  464. }
  465.  
  466. //•    --------------------    DoAdjustMenu
  467.  
  468. static void
  469. DoAdjustMenu(MenuRef m, UInt32 options, UInt32 updateFrequency, UInt32 messageSize)
  470. {
  471.     if (options & kNSpSendFlag_Junk)
  472.         SetItemMark(m, iJunk, checkMark);
  473.     else
  474.         SetItemMark(m, iJunk, noMark);
  475.  
  476.     if (options & kNSpSendFlag_Normal)
  477.         SetItemMark(m, iNormal, checkMark);
  478.     else
  479.         SetItemMark(m, iNormal, noMark);
  480.  
  481.     if (options & kNSpSendFlag_Registered)
  482.         SetItemMark(m, iRegistered, checkMark);
  483.     else
  484.         SetItemMark(m, iRegistered, noMark);
  485.         
  486.     if (options & kNSpSendFlag_Blocking)
  487.         SetItemMark(m, iBlocking, checkMark);
  488.     else
  489.         SetItemMark(m, iBlocking, noMark);
  490.         
  491.     SetItemMark(m, i1X, noMark);
  492.     SetItemMark(m, i10X, noMark);
  493.     SetItemMark(m, i30X, noMark);
  494.     SetItemMark(m, iNoLimit, noMark);
  495.     switch(updateFrequency)
  496.     {
  497.         case 60:
  498.             SetItemMark(m, i1X, checkMark);
  499.         break;
  500.         case 6:
  501.             SetItemMark(m, i10X, checkMark);
  502.         break;
  503.         case 2:
  504.             SetItemMark(m, i30X, checkMark);
  505.         break;
  506.         default:
  507.             SetItemMark(m, iNoLimit, checkMark);
  508.         break;
  509.     }
  510.  
  511.     SetItemMark(m, iLess500, noMark);
  512.     SetItemMark(m, i1K, noMark);
  513.     SetItemMark(m, i10K, noMark);
  514.     SetItemMark(m, i100K, noMark);
  515.     switch(messageSize)
  516.     {
  517.         case 400:
  518.             SetItemMark(m, iLess500, checkMark);
  519.         break;
  520.         case 1024:
  521.             SetItemMark(m, i1K, checkMark);
  522.         break;
  523.         case 10240:
  524.             SetItemMark(m, i10K, checkMark);
  525.         break;
  526.         case 102400:
  527.             SetItemMark(m, i100K, checkMark);
  528.         break;
  529.     }
  530.     
  531. }    
  532.  
  533. //•    --------------------    AdjustNetMenus
  534.  
  535. void
  536. AdjustNetMenus(void)
  537. {
  538.     MenuRef m = GetMenu(131);
  539.     
  540.     DoAdjustMenu(m, gSendOptions, gUpdateFrequency, gPlayerMessageSize);
  541.  
  542.     if (gHost)
  543.     {
  544.         m = GetMenu(132);
  545.         if (m)
  546.             DoAdjustMenu(m, gHostSendOptions, gHostUpdateFrequency, gGameStateMessageSize);
  547.     }
  548. }
  549.  
  550. //•    --------------------    DoHost
  551.  
  552. OSStatus
  553. DoHost(void)
  554. {
  555.     OSStatus     status;
  556.     Str255        chooserName;
  557.     NSpProtocolListReference    theList = NULL;
  558.     Boolean okHit;
  559.     
  560. //    Create an empty protocol list
  561.     status = NSpProtocolList_New(NULL, &theList);
  562.     if (status != noErr)
  563.     {
  564.         printf("NSpProtocolList_New returned error: %d\n", status);
  565.         goto failure;
  566.     }
  567.     
  568. //    Now present a UI for the hosting
  569. //    Note!  Do NOT pass in string constants, as the user can change these values
  570.     GetChooserName(chooserName);
  571.     PLstrncpy(playerName, chooserName, 31);    
  572.     PLstrcpy(gameName, "\pNetSprocket Test");
  573.     password[0] = 0;
  574.     
  575.     okHit = NSpDoModalHostDialog(theList, gameName, playerName, password, nil);
  576.     if (!okHit)
  577.     {
  578.         status = kUserCancelled;
  579.         goto failure;
  580.     }
  581.  
  582.     //    Now host the game
  583.     status = NSpGame_Host(&gNetGame, theList, kMaxPlayers, gameName,
  584.                 password, playerName, 0, kNSpClientServer, 0);
  585.     if (status != noErr)
  586.     {
  587.         printf("NSpGame_Host returned error %d\n", status);
  588.         goto failure;
  589.     }
  590.     
  591.     gHost = true;
  592.     
  593.     
  594.     if (status == noErr)
  595.         AddHostMenu();
  596.         
  597.     return status;
  598.     
  599. failure:
  600.     if (theList != nil)
  601.         NSpProtocolList_Dispose(theList);
  602.         
  603.     return status;
  604. }
  605.  
  606. //•    --------------------    DoJoin
  607.  
  608. OSStatus
  609. DoJoin(void)
  610. {
  611.     NSpAddressReference    theAddress;
  612.     OSStatus            status;
  613.     Str255                chooserName;
  614.     
  615.     GetChooserName(chooserName);
  616.     PLstrncpy(playerName, chooserName, 31);    
  617.     password[0] = 0;
  618.     
  619. //    Present the UI for joining a game
  620. //    passing an empty string (not nil) for the type causes NetSprocket to use
  621. //    the game id passed in to initialize
  622.     theAddress = NSpDoModalJoinDialog("\p", kJoinDialogLabel, playerName, password, NULL);
  623.     if (theAddress == NULL)        // The user cancelled
  624.         return kUserCancelled;
  625.     
  626.     
  627.     status = NSpGame_Join(&gNetGame, theAddress, playerName, password, 0, NULL, 0, 0);
  628.     if (status != noErr)
  629.         printf("NSpGame_Join returned error %d\n", status);
  630.     else        
  631.         gHost = false;    
  632.  
  633.     return status;
  634. }
  635.  
  636. //•    --------------------    DoSendLeaveMessage
  637.  
  638. static void
  639. DoSendLeaveMessage(NSpPlayerID inID)
  640. {
  641. NSpMessageHeader m;
  642. OSStatus status;
  643.     
  644.     NSpClearMessageHeader(&m);
  645.     
  646.     m.what = kLeaveMessage;
  647.     m.to = inID;
  648.     m.messageLen = sizeof(NSpMessageHeader);
  649.  
  650.     status = NSpMessage_Send(gNetGame, &m, kNSpSendFlag_Registered);
  651.  
  652. }
  653.  
  654. //•    --------------------    DoCloseNetWindow
  655.  
  656. void
  657. DoCloseNetWindow(WindowPtr inWindow)
  658. {
  659.     if (gHost)
  660.     {
  661.         WindowStuff *stuff = (WindowStuff *) GetWRefCon(inWindow);    
  662.         DoSendLeaveMessage(stuff->id);
  663.     }
  664.     else
  665.         ShutdownNetworking();
  666.     
  667. }
  668.  
  669. //•    --------------------    DoHandleMessage
  670.  
  671. static void
  672. DoHandleMessage(NSpMessageHeader *inMessage)
  673. {
  674.     switch (inMessage->what)
  675.     {
  676.         case kLeaveMessage:
  677.             printf("Got a message telling us to leave the game.");
  678.             ShutdownNetworking();
  679.         break;
  680.         case kNSpPlayerJoined:
  681.         {
  682.             NSpPlayerJoinedMessage *theMessage = (NSpPlayerJoinedMessage *) inMessage;
  683.             printf("Got player joined message: %d\n", theMessage->playerInfo.id);
  684.  
  685.             if (gHost || theMessage->playerInfo.id == NSpPlayer_GetMyID(gNetGame))
  686.             {
  687.                 gMyPlayerID = NSpPlayer_GetMyID(gNetGame);
  688.                 WindowPtr wind = GetNewCWindow(128, nil, (WindowPtr) -1L);
  689.                 if (!wind)
  690.                     printf("Failed to create a new window!\n");
  691.                 else
  692.                 {
  693.                     WindowStuff *stuff = GetFreeWindowStuff();
  694.                     if (stuff == nil)
  695.                     {
  696.                         printf("Couldn't alloc memory to show window.\n");
  697.                         DisposeWindow(wind);
  698.                     }
  699.                     else
  700.                     {
  701.                         stuff->id = theMessage->playerInfo.id;
  702.                         stuff->lastMessage = 0;
  703.                         PLstrcpy(stuff->text, "\pNew Player");
  704.                         
  705.                         SetWTitle(wind,theMessage->playerInfo.name);
  706.                         SetWRefCon(wind, (long) stuff);
  707.                         InvalPlayerWindow(stuff->id);
  708.                     }
  709.                 }
  710.             }
  711.         }    
  712.         break;
  713.             
  714.         case kNSpPlayerLeft:
  715.         {
  716.         char    name[32];
  717.         
  718.             NSpPlayerLeftMessage *theMessage = (NSpPlayerLeftMessage *) inMessage;
  719.  
  720.             BlockMoveData(theMessage->playerName + 1, name, theMessage->playerName[0]);
  721.             name[theMessage->playerName[0]] = '\0';
  722.             
  723.             printf("Got player left message: %s, player #%d\n", name, theMessage->playerID);
  724.             
  725.  
  726.             if (gHost)
  727.             {
  728.                 WindowPtr w = FindPlayersWindow(theMessage->playerID);
  729.                 if (w)
  730.                 {
  731.                     WindowStuff *stuff = (WindowStuff *) GetWRefCon(w);
  732.                     ReleaseWindowStuff(stuff);
  733.                     DisposeWindow(w);
  734.                 }
  735.                 else
  736.                     printf("Didn't find the window for the player that left!!\n");
  737.             }    
  738.         }
  739.         break;
  740.         case kNSpGameTerminated:
  741.             printf("Got Game terminated message\n");
  742.             ShutdownNetworking();
  743.         break;
  744.                         
  745.         default:
  746.             break;
  747.     }
  748.  
  749. }
  750.  
  751. //•    --------------------    GetMessages
  752.  
  753. static void
  754. GetMessages(void)
  755. {    
  756. NSpMessageHeader    *theMessage;
  757.     
  758.     do 
  759.     {
  760.         theMessage = NSpMessage_Get(gNetGame);
  761.         DoHandleMessage(theMessage);
  762.         NSpMessage_Release(gNetGame, theMessage);
  763.     } while (gNetGame && theMessage != NULL);
  764.     
  765. }
  766.  
  767. //•    --------------------    UpdateNetWindows
  768.  
  769. static void
  770. UpdateNetWindows(void)
  771. {
  772. WindowPtr    w;
  773.  
  774.     w = FrontWindow();
  775.  
  776.     while (w != nil)
  777.     {
  778.         WindowStuff *stuff = (WindowStuff *) GetWRefCon(w);
  779.         if (stuff && stuff->changed)
  780.         {
  781.             GrafPtr        oldPort;
  782.         
  783.             GetPort(&oldPort);
  784.             SetPort(w);
  785.             RefreshWindow(w);
  786.             SetPort(oldPort);
  787.             
  788.             stuff->changed = false;
  789.         }
  790.         w = GetNextWindow(w);        
  791.     }
  792. }
  793.  
  794. //•    --------------------    HandleNetwork
  795.  
  796. void
  797. HandleNetwork(void)
  798. {
  799. OSStatus    status;
  800.  
  801.     if (!gNetGame)
  802.         return;
  803.  
  804.     GetMessages();
  805.  
  806. //    update any windows as necessary
  807.     UpdateNetWindows();
  808.     
  809.     UInt32 time = TickCount();
  810.     
  811.     if (gNetGame && time > gLastUpdate + gUpdateFrequency)
  812.     {
  813.         NSpClearMessageHeader(&gPlayerMessage.h);
  814.  
  815.         gPlayerMessage.h.what = kPlayerInputMessage;
  816.         gPlayerMessage.h.to = kNSpHostOnly;
  817.         gPlayerMessage.h.messageLen = gPlayerMessageSize;
  818.  
  819. //        Send my info to the host
  820.         status = NSpMessage_Send(gNetGame, &gPlayerMessage.h, gSendOptions);
  821.         if (status != noErr)
  822.             printf("NSpMessage_Send returned error: %d\n", status);
  823.         
  824.         if (gHost && time > gLastHostUpdate + gHostUpdateFrequency)
  825.         {
  826.             NSpClearMessageHeader(&gGameStateMessage.h);
  827.  
  828.             gGameStateMessage.h.what = kGameStateMessage;
  829.             gGameStateMessage.h.to = kNSpAllPlayers;
  830.             gGameStateMessage.h.messageLen = gGameStateMessageSize;
  831.  
  832.     //        Send my info to the host
  833.             status = NSpMessage_Send(gNetGame, &gGameStateMessage.h, gHostSendOptions);
  834.             if (status != noErr)
  835.                 printf("NSpMessage_Send returned error: %d\n", status);
  836.             
  837.             gLastHostUpdate = time;
  838.         }
  839.  
  840.         gLastUpdate = time;
  841.     }        
  842. }
  843.  
  844. //•    --------------------    GetInfoEnumeratePlayers
  845.  
  846. static void
  847. GetInfoEnumeratePlayers(void)
  848. {
  849. OSStatus    theErr;
  850. NSpPlayerEnumerationPtr    thePlayers;
  851. UInt32        i;
  852.  
  853.     if (nil == gNetGame)
  854.         printf("gNetGame is nil.\n");
  855.  
  856.     theErr = NSpPlayer_GetEnumeration(gNetGame,    &thePlayers);
  857.     if (noErr != theErr)
  858.     {
  859.         printf("NSpPlayer_GetEnumeration returned %ld\n", theErr);
  860.         return;
  861.     }
  862.     
  863.         printf("PlayerID    Name\n");
  864.         printf("--------    -------------------------------\n");
  865.     for (i = 0; i < thePlayers->count; i++)
  866.     {
  867.     char                name[sizeof (NSpPlayerName)];
  868.     NSpPlayerInfoPtr    thePlayer;
  869.     
  870.         NSpPlayer_GetInfo(gNetGame, thePlayers->playerInfo[i]->id, &thePlayer);
  871.     
  872.         BlockMoveData(thePlayer->name + 1, name, thePlayer->name[0]);
  873.         name[thePlayer->name[0]] = '\0';
  874.         printf("%0.8ld    %s\n", thePlayer->id, name);
  875.     }
  876. }
  877.  
  878. //•    --------------------    EnumeratePlayers
  879.  
  880. static void
  881. EnumeratePlayers(void)
  882. {
  883. OSStatus    theErr;
  884. NSpPlayerEnumerationPtr    thePlayers;
  885. UInt32        i;
  886.  
  887.     if (nil == gNetGame)
  888.         printf("gNetGame is nil.\n");
  889.  
  890.     theErr = NSpPlayer_GetEnumeration(gNetGame,    &thePlayers);
  891.     if (noErr != theErr)
  892.     {
  893.         printf("NSpPlayer_GetEnumeration returned %ld\n", theErr);
  894.         return;
  895.     }
  896.     
  897.         printf("PlayerID    Name\n");
  898.         printf("--------    -------------------------------\n");
  899.     for (i = 0; i < thePlayers->count; i++)
  900.     {
  901.     char    name[sizeof (NSpPlayerName)];
  902.     
  903.         BlockMoveData(thePlayers->playerInfo[i]->name + 1, name, thePlayers->playerInfo[i]->name[0]);
  904.         name[thePlayers->playerInfo[i]->name[0]] = '\0';
  905.         printf("%0.8ld    %s\n", thePlayers->playerInfo[i]->id, name);
  906.     }
  907. }
  908.